/**  
 * @Title:       SerialNumberUtil.java   
 * @Package:     com.ces.component.archive.utils   
 * @Description: TODO(用一句话描述该文件做什么)   
 * @author:      yulihua     
 * @date:        2019-4-15 下午3:18:11   
 * @version:     V1.0 
 * @Copyright:   2019 ces All rights reserved. 
 */
package org.springblade.demo05.utils;
import java.io.*;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ces.config.dhtmlx.entity.menu.Menu;
import com.ces.config.dhtmlx.entity.parameter.SystemParameter;
import com.ces.config.dhtmlx.entity.resource.Resource;
import com.ces.config.dhtmlx.service.menu.MenuService;
import com.ces.config.dhtmlx.service.parameter.SystemParameterService;
import com.ces.config.dhtmlx.service.resource.ResourceService;
import com.ces.config.utils.EhcacheUtil;
import com.ces.config.utils.SystemParameterUtil;
import com.ces.xarch.core.web.listener.XarchListener;

import ces.filecheck.engine.checkitems.Util;
/**
 * @ClassName: SerialNumberUtil
 * @Description:TODO(这里用一句话描述这个类的作用)
 * @author: yulihua
 * @date: 2019-4-15 下午3:18:11
 * 
 * @Copyright: 2019 ces All rights reserved.
 */
public class SerialNumberUtil {
    // 序列号文件名称
    private static final String SERIALNUMBER_FILENAME = "key.license";
    // 序列号校验码文件名称
    private static final String SERIALNUMBER_MD5_FILENAME = "key.license.md5";
    // 系统id
    private static final String SYSTEM_ID = "40287c8158d1c1d20158d1c942570000";
    /**
     * 校验序列号
     * 
     * @Title: verifySerialNumber
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author: yulihua
     * @date: 2019-4-15 下午3:44:13
     * @param @param rootPath
     * @return: void
     * @throws:
     */
    public static void verifySerialNumber(String rootPath) {
        FileReader reader = null;
        BufferedReader br = null;       
        FileInputStream fis=null;
        InputStreamReader isr=null;
        try {
            String filePath = rootPath + File.separator + SERIALNUMBER_FILENAME;
            File file = new File(filePath);
            if (!file.exists()) {
                System.out.println("系统未注册！");
                //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统未注册！请联系管理员！");
                return;
            }          
            //key.license文件是否有更新
            boolean serialNumberIsModify=true;
            String md5filePath = rootPath + File.separator + SERIALNUMBER_MD5_FILENAME;
            File md5File = new File(md5filePath);
            //记录的md5值
            StringBuffer serialNumberMd5Str = new StringBuffer();
        
            if (md5File.exists()) {
                String md5 = Util.md5Encode(file, "md5"); 
                reader = new FileReader(md5filePath);
                br = new BufferedReader(reader);
                String line;
                while ((line = br.readLine()) != null) {
                    serialNumberMd5Str.append(line);
                }
                if (md5.equals(serialNumberMd5Str.toString())) {// 根据md5的值判断key.license文件是否有更新
//                    System.out.println("key.license文件未更新！");
                    serialNumberIsModify=false;
                } 
            }
            
            //注册码
            StringBuffer serialNumberStr = new StringBuffer();
//            reader = new FileReader(filePath);
//            br = new BufferedReader(reader);
            fis=new FileInputStream(filePath);
            isr=new InputStreamReader(fis,"UTF-8");
            br=new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                if(line.startsWith("注册码:")){
                    serialNumberStr.append(line.substring("注册码:".length()));  
                }
            }
            String deCoderStr = EncryptUtils.decrypt(serialNumberStr.toString());
//            System.out.println("deCoderStr=" + deCoderStr);
            JSONObject jsonObj = JSONObject.parseObject(deCoderStr);
            //产品名称
            String productName = jsonObj.get("productName").toString();
//            System.out.println("productName=" + productName);
            //企业名称
            String enterpriseName = jsonObj.get("enterpriseName").toString();
//            System.out.println("enterpriseName=" + enterpriseName);
            
            
            //全宗个数
//            String fathersNum = jsonObj.get("fathersNum").toString();//fathersNum值为0表示不控制全宗数
////            System.out.println("fathersNum=" + fathersNum);
//            if(!"0".equals(fathersNum)){
//                EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "QzCount", fathersNum);
//            }
            //有效期（天数）
            String vaildTime = jsonObj.get("vaildTime").toString();
//            System.out.println("vaildTime=" + vaildTime);
            if (vaildTime != null && !"0".equals(vaildTime)) {//vaildTime值为0表示是正式版     如果是试用版，计算到期日期  
                int vaildDays = Integer.parseInt(vaildTime);
                //注册时间
                String actTime = jsonObj.get("actTime").toString();
//                System.out.println("actTime=" + actTime);
                //计算出试用到期日期
                Date validEndDate = DateTimeUtil.getDateBeforeOrAfter(DateTimeUtil.getFormatDate(actTime, "yyyy-MM-dd HH:mm:ss"), vaildDays);
                //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "validEndDate", validEndDate);
                String validEndDateStr = DateTimeUtil.getFormatDateTime(validEndDate);
//                System.out.println("validEndDateStr=" + validEndDateStr);
                int betweenDates = DateTimeUtil.getDaysBetweenDates(DateTimeUtil.getCurrDate(), validEndDate);
//                System.out.println("betweenDates=" + betweenDates);
                if (betweenDates < 0) {
                    //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "试用版已到期！请联系管理员！");
//                    System.out.println("试用版已到期！");
                    return;
                }
            }
            
            //MAC地址验证
//            //企业机器码
//            String machineCode = jsonObj.get("machineCode").toString();
//            String serverMacMedia = License.getMac();
//            String os = getOSName();
//            System.out.println(os);
//            if (os.startsWith("windows")) {
//                // 本地是windows
//	            	String mac = "";
//	                String[] serverMacsMedia=null;
//	                System.out.println(os);
//	                mac = License.getMac();
//	                serverMacsMedia = mac.split(",");
//                    System.out.println(serverMacsMedia+"=============serverMacsMedia");
//                	if (!isHave(serverMacsMedia,machineCode)) {
//                        EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册MAC地址有误！请联系管理员！");
//                        System.out.println("系统注册MAC地址有误！");
//                        return;
//                    }
//            } else {
//                // 本地是非windows系统 一般就是unix
//                List<String> listMacLinux = getMACAddressByLinux();
//				System.out.println(listMacLinux+"===============listMacLinux");
//				if (!isHaveLinux(listMacLinux,machineCode)) {
//					EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册MAC地址有误！请联系管理员！");
//					System.out.println("系统注册MAC地址有误！");
//					return;
//				}
//
//            }
           
            //下面注释掉的方法无法获取 无ip时的mac，故注释掉
            /*String serverMac = CommonUtil.getLocalMacAddress();
            if("".equals(serverMac)|| serverMac==""){
                serverMac = License.getMac();
            }
//            System.out.println("serverMac="+serverMac);
            if (!serverMac.equals(machineCode)) {
                EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册MAC地址有误！请联系管理员！");
//                System.out.println("系统注册MAC地址有误！");
                return;
            }*/
            
            //key.license文件有更新
            if(serialNumberIsModify){
            	//更新系统参数“版权信息”的值
                SystemParameterService systemParameterService = XarchListener.getBean(SystemParameterService.class);
                SystemParameter  copyrightSp=systemParameterService.getSystemParameterByNameAndSystemId("版权信息", "-1");
                copyrightSp.setValue(enterpriseName);
                systemParameterService.save(copyrightSp);
                //放入缓存
                SystemParameterUtil.getInstance().putSystemParamValue(copyrightSp.getSystemId(),
                copyrightSp.getCode(), copyrightSp.getValue());
                SystemParameterUtil.getInstance().putSystemParamValue1(copyrightSp.getId(),
                copyrightSp.getValue());
              //MAC地址验证
                //企业机器码
                String machineCode = jsonObj.get("machineCode").toString();
                String os = getOSName();
                
                if (os.startsWith("windows")) {
                    // 本地是windows

                    String mac1 = getMac();
                    String[] serverMacsMedia=mac1.split(",");;
                    System.out.println(os);
                    System.out.println("本机mac= 【"+mac1+"】  授权文件的mac"+machineCode);
                	if (!isHave(serverMacsMedia,machineCode)) {
                        //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册MAC地址有误！请联系管理员！");
                        System.out.println("系统注册MAC地址有误！");
                        return;
                    }
                } else {
                	List<String> listMacLinux = getMACAddressByLinux();
                	System.out.println(listMacLinux+"===============listMacLinux");
                	if (!isHaveLinux(listMacLinux,machineCode)) {
                        //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册MAC地址有误！请联系管理员！");
                        System.out.println("系统注册MAC地址有误！");
                        return;
                    }
                    // 本地是非windows系统 一般就是unix
//                	serverMacsMedia = getMACAddressByLinux();
                }
                //启用、禁用菜单
                List<String> menuIdList = new ArrayList<String>();
                MenuService menuService = XarchListener.getBean(MenuService.class);
//                System.out.println("machineCode=" + machineCode);
                String projectMenu = jsonObj.get("projectMenu").toString();
                JSONArray jsonArray = JSONArray.parseArray(projectMenu);
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject2 = jsonArray.getJSONObject(i);
                    String menuId = jsonObject2.get("menu_id").toString();
                    menuIdList.add(menuId);
                    String menuName = jsonObject2.get("name").toString();
                    System.out.println("menuCode=" + menuId);
                    System.out.println("menuName=" + menuName);
//                    System.out.println("menuCode=" + menuCode);
//                    System.out.println("menuName=" + menuName);
                }
//                System.out.println("menuIdList=" + menuIdList);
                ResourceService resourceService = XarchListener.getBean(ResourceService.class);
                Resource resourceRoot = resourceService.getByTargetId(SYSTEM_ID);
                List<Resource> resourceSystemLevel=resourceService.getByParentIdAndType(resourceRoot.getId(), "0");//一级菜单对应的资源
                List<Resource> resourceFirstLevels = new ArrayList<Resource>();
                List<String> resourceIdsFirstLevel=new ArrayList<String>();
                for (Resource resource : resourceSystemLevel) {//先把已禁用的一级菜单资源启用，不然后面可能会报错
                    if(resource.getCanUse().equals("0")){
                        resource.setCanUse("1");
                        resourceService.disableOrEnableResourse(resource.getId(), "enable");
                    }
                    List<Resource> resourceFirstLevel=resourceService.getByParentIdAndType(resource.getId(), "0");//一级菜单对应的资源
                    resourceFirstLevels.addAll(resourceFirstLevel);
                    resourceIdsFirstLevel.add(resource.getId());
                }
                for(Resource resource : resourceFirstLevels) {                    
                	if(resource.getCanUse().equals("0")){
                        resource.setCanUse("1");
                        resourceService.disableOrEnableResourse(resource.getId(), "enable");
                    }
                    resourceIdsFirstLevel.add(resource.getId());
                }
                List<Resource> resourceList = resourceService.getBySystemId(SYSTEM_ID);
                for(Resource resource : resourceList) {                    
                    if(!resourceIdsFirstLevel.contains(resource.getId())){//先处理二级菜单
                    	System.out.println("resource=" + resource.getName());
                        if (menuIdList.contains(resource.getTargetId())) {
                            if(resource.getCanUse().equals("0")){
                                resource.setCanUse("1");
                                resourceService.disableOrEnableResourse(resource.getId(), "enable");
                            }
                        } else {
                            if(resource.getCanUse().equals("1")){
                                resource.setCanUse("0");
                                resourceService.disableOrEnableResourse(resource.getId(), "disable");
                            }
                        }
                    }
                }
                for (Resource resource : resourceFirstLevels) {//再处理一级菜单
                	System.out.println("resource=" + resource.getName());
                    if (menuIdList.contains(resource.getTargetId())) {
                        if(resource.getCanUse().equals("0")){
                            resource.setCanUse("1");
                            resourceService.disableOrEnableResourse(resource.getId(), "enable");
                        }
                    } else {
                        if(resource.getCanUse().equals("1")){
                            resource.setCanUse("0");
                            resourceService.disableOrEnableResourse(resource.getId(), "disable");
                        }
                    }
                }
                for (Resource resource : resourceSystemLevel) {//再处理一级菜单
                	System.out.println("resource=" + resource.getName());
                    if (menuIdList.contains(resource.getTargetId())) {
                        if(resource.getCanUse().equals("0")){
                            resource.setCanUse("1");
                            resourceService.disableOrEnableResourse(resource.getId(), "enable");
                        }
                    } else {
                        if(resource.getCanUse().equals("1")){
                            resource.setCanUse("0");
                            resourceService.disableOrEnableResourse(resource.getId(), "disable");
                        }
                    }
                }
                //生成md5文件，记录md5值
                SerialNumberUtil.getMD5(filePath, md5filePath);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册不成功，读取序列号文件出错！请联系管理员！");
//            System.out.println("系统注册不成功，读取序列号文件出错！");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册不成功，读取序列号文件出错！请联系管理员！");
//            System.out.println("系统注册不成功，读取序列号文件出错！");
        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //EhcacheUtil.setCache("SERIAL_NUMBER_CHECK", "failmessage", "系统注册不成功，读取序列号文件出错！请联系管理员！");
//            System.out.println("系统注册不成功，读取序列号文件出错！");
        } finally {
            try {
                if(reader!=null){
                    reader.close();
                }
                if(br!=null){
                    br.close();
                }
                if(fis!=null){
                    fis.close();
                }
                if(isr!=null){
                    isr.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    /**
     * 试用期限还剩多少天
     * @Title:       getValidDays   
     * @Description: TODO(这里用一句话描述这个方法的作用)  
     * @author:      yulihua    
     * @date:        2019-4-18 下午3:44:22  
     * @param        @return        
     * @return:      String      
     * @throws:
     */
    public static String getValidDays(){
        Object validEndDate=EhcacheUtil.getCache("SERIAL_NUMBER_CHECK", "validEndDate");
        if(validEndDate!=null){
            Date validEndDateD=(Date)validEndDate;
            int betweenDates = DateTimeUtil.getDaysBetweenDates(DateTimeUtil.getCurrDate(), validEndDateD);
            return String.valueOf(betweenDates);
        }
        return "";//返回空表示是正式版，不需判断是否到期
    }
    /**
     * 生成md5文件
     * 
     * @Title: getMD5
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author: yulihua
     * @date: 2019-4-15 下午3:41:21
     * @param @param filepath
     * @param @param md5FilePath
     * @return: void
     * @throws:
     */
    public static void getMD5(String filepath, String md5FilePath) {
        try {
            String md5 = Util.md5Encode(new File(filepath), "md5");
            System.out.println("---------------md5------" + md5);
            if (!new File(filepath).isDirectory()) {
                new File(filepath).mkdirs();
            }
            File md5File = new File(md5FilePath);
            if (!md5File.exists()) {
                md5File.createNewFile();
            }
            FileWriter resultFile = new FileWriter(md5File);
            PrintWriter myFile = new PrintWriter(resultFile);
            myFile.println(md5);
            myFile.close();
            resultFile.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * @Description 此方法有两个参数，第一个是要查找的字符串数组，第二个是要查找的字符或字符串
     * @modify 	
     * @date 2019年4月25日
     * @author lenovo
     * @return
      */
     public static boolean isHave(String[] strs,String s){
     	for(int i=0;i<strs.length;i++){
 			if(strs[i].indexOf(s)!=-1){
 				return true;
 			}
     	}
     	return false;
 	}
     
     private static String getOSName() {
         return System.getProperty("os.name").toLowerCase();
     }

    
     private static String getUnixMACAddress() {
         String mac = null;
         BufferedReader bufferedReader = null;
         Process process = null;
         try {
             process = Runtime.getRuntime().exec("ifconfig eth0");// linux下的命令，一般取eth0作为本地主网卡 显示信息中包含有mac地址信息
             bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
             String line = null;
             int index = -1;
             while ((line = bufferedReader.readLine()) != null) {
                 index = line.toLowerCase().indexOf("hwaddr");// 寻找标示字符串[hwaddr]
                 if (index >= 0) {// 找到了
                     mac = line.substring(index + "hwaddr".length() + 1).trim();// 取出mac地址并去除2边空格
                     break;
                 }
             }
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             try {
                 if (bufferedReader != null) {
                     bufferedReader.close();
                 }
             } catch (IOException e1) {
                 e1.printStackTrace();
             }
             bufferedReader = null;
             process = null;
         }

         return mac.toUpperCase();
     }

    
     private static String getWindowsMACAddress() throws UnknownHostException, SocketException {
         InetAddress ia = InetAddress.getLocalHost();
         // 获取网卡，获取地址
         byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
         // System.out.println("mac数组长度："+mac.length);
         StringBuffer sb = new StringBuffer("");
         for (int i = 0; i < mac.length; i++) {
             if (i != 0) {
                 sb.append("-");
             }
             // 字节转换为整数
             int temp = mac[i] & 0xff;
             String str = Integer.toHexString(temp);
             // System.out.println("每8位:"+str);
             if (str.length() == 1) {
                 sb.append("0" + str);
             } else {
                 sb.append(str);
             }
         }
         System.out.println("本机MAC地址:" + sb.toString().toUpperCase());
         return sb.toString().toUpperCase();
     }
	 
	 private static List<String>  getMACAddressByLinux() throws Exception {
    	 java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
         StringBuilder sb = new StringBuilder();
         ArrayList<String> tmpMacList=new ArrayList<>();
         while(en.hasMoreElements()){
             NetworkInterface iface = en.nextElement();
             List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
             for(InterfaceAddress addr : addrs) {
                 InetAddress ip = addr.getAddress();
                 NetworkInterface network = NetworkInterface.getByInetAddress(ip);
                 if(network==null){continue;}
                 byte[] mac = network.getHardwareAddress();
                 if(mac==null){continue;}
                 sb.delete( 0, sb.length() );
                 for (int i = 0; i < mac.length; i++) {sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : ""));}
                 if(!tmpMacList.contains(sb.toString())){
                	 tmpMacList.add(sb.toString().toLowerCase());
                 }
             }        
         }
         if(tmpMacList.size()<=0){return tmpMacList;}
         return tmpMacList;
     }
	 
	 public static boolean isHaveLinux(List<String> list,String s){
    	 System.out.println(s+"==============s");
		if(list.contains(s.toLowerCase())){
			System.out.println(1+"==============1");
			return true;
		}
      	System.out.println(1+"==============1");
      	return false;
  	}
	 
	 public static void main(String[] args) {
		 String mac = License.getMac();
		 System.out.println(mac);
	}


    /**
     * 获取MAC地址
     * @return MAC地址
     */
    public static String getMac() {
        String macTemp = "";
        // 判断当前是什么操作系统
        String os = System.getProperty("os.name");
        Process proc = null;
        BufferedInputStream in = null;
        BufferedReader reader = null;
        try {
            if(os.toLowerCase().startsWith("win")){
                System.out.println(os + " can't gunzip");
                String command = "ipconfig /all";
                proc = Runtime.getRuntime().exec(command);
                in = new BufferedInputStream(proc.getInputStream());
                reader = new BufferedReader(new InputStreamReader(in, "GBK"));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    if (line.indexOf("Physical Address") != -1 || line.indexOf("物理地址") != -1 ) {
                        macTemp =macTemp+","+line.substring(line.indexOf("Physical Address") + 36,
                                line.length());
                        // break;
                    }
                }
                if(macTemp.startsWith(",")){
                    macTemp=macTemp.substring(1,macTemp.length());
                }

            }else{
                System.out.println(os + " can't gunzip");
                proc = Runtime.getRuntime().exec("ifconfig eth0");
                in = new BufferedInputStream(proc.getInputStream());
                reader = new BufferedReader(new InputStreamReader(in));
                //BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    Pattern pat = Pattern.compile("\\b\\w+:\\w+:\\w+:\\w+:\\w+:\\w+\\b");
                    Matcher mat= pat.matcher(line);
                    if(mat.find()){
                        macTemp=mat.group(0);
                        //break;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return macTemp;
    }
}